#include "D3D11Renderer.h"

//Complete includes (manager classes)
#include "ShaderManager.h"

//Include debug draw quad effect
#include "TexturedFullScreenQuadFX.h"

//Complete includes for effects.
#include "TileForwardNormalMapFX.h"
#include "TileForwardTextureMapFX.h"
#include "TileForwardDisplacementMappingFX.h"
#include "TileForwardSolidColourFX.h"

//For instancing effects
#include "TileForwardNormalMapInstFX.h"
#include "TileForwardTextureMapInstFX.h"
#include "TileForwardSolidColourInstFX.h"
#include "TileForwardDisplacementMapInstFX.h"

//Animation effects
#include "TileForwardAnimNormalMapFX.h"
#include "TileForwardAnimTextureMapFX.h"
#include "TileForwardAnimSolidColourFX.h"

//Init static data
D3D11Renderer* D3D11Renderer::instance = 0;

D3D11Renderer::D3D11Renderer()
{
	//Get pointer to shader manager.
	ShaderManager* sharedShaderManager = ShaderManager::GetInstance();

	//Get debug draw effect
	debugDrawTexQuadEffect = sharedShaderManager->ReturnTexturedFullScreenQuadFX();

	//Get effect pointers from the shader manager.
	textureMappingEffect = sharedShaderManager->ReturnTileForwardTextureMapFX();
	normalMappingEffect = sharedShaderManager->ReturnTileForwardNormalMapFX();
	displacementMappingEffect = sharedShaderManager->ReturnTileForwardDisplacementMappingFX();
	tileForwardSolidColourEffect = sharedShaderManager->ReturnTileForwardSolidColourFX();

	//Instanced effects
	normalMappingInstEffect = sharedShaderManager->ReturnTileForwardNormalMapInstFX();
	textureMappingInstEffect = sharedShaderManager->ReturnTileForwardTextureMapInstFX();
	solidColourInstEffect = sharedShaderManager->ReturnTileForwardSolidColourInstFX();
	dispMappingInstEffect = sharedShaderManager->ReturnTileForwardDisplacementMapInstFX();

	//Animation effects
	animNormalMapFX = sharedShaderManager->ReturnTileForwardAnimNormalMapFX();
	animTexMapFX = sharedShaderManager->ReturnTileForwardAnimTextureMapFX();
	animSolidColourFX = sharedShaderManager->ReturnTileForwardAnimSolidColourFX();
}

D3D11Renderer::~D3D11Renderer()
{}

D3D11Renderer* D3D11Renderer::GetInstance()
{
	if (!instance)
		instance = new D3D11Renderer();

	return instance;
}

void D3D11Renderer::Release()
{
	if (instance)
	{
		delete instance;
		instance = 0;
	}
}

//
//Debug rendering
//
void D3D11Renderer::DebugDrawTexture(ID3D11DeviceContext* context, 
	ID3D11Buffer* vb, ID3D11Buffer* ib, 
	ID3D11ShaderResourceView* tex,
	CXMMATRIX &proj,
	bool msaaTex,
	LPCSTR techName)
{
	//Set active technique for the quad effect. 
	debugDrawTexQuadEffect->SetActiveTechniqueByName(techName);

	//Set IA Stage of the pipeline.
	UINT stride = sizeof(TexturedFullScreenQuadFX::PosTex);
	UINT offset = 0;
	context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	context->IASetInputLayout(debugDrawTexQuadEffect->ReturnInputLayout());
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);

	//Set variables for this effect.
	if (!msaaTex)
		debugDrawTexQuadEffect->SetShaderResource(tex);
	else
		debugDrawTexQuadEffect->SetShaderResourceMSAA(tex);
	debugDrawTexQuadEffect->SetProj(proj);

	//Draw
	for (unsigned p = 0; p < debugDrawTexQuadEffect->ReturnActiveTechniqueNumberOfPasses(); p++)
	{
		debugDrawTexQuadEffect->ApplyActiveTechniqueForPass(p, context);
		context->DrawIndexed(6, 0, 0);
	}

	//Unbind resource.
	static ID3D11ShaderResourceView* nullSRV[] = {NULL};
	context->PSSetShaderResources(0,1,&nullSRV[0]);
}

//
//Renders geometry.
//

void D3D11Renderer::RenderWithTileForwardTextureMapFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture, 
		unsigned drawCount,
		unsigned drawStart,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex, 
		bool shouldSampleSSAO)
{
	//Set technique
	if (isShadowPass)
		textureMappingEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			textureMappingEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else
		{
			if (shouldSampleSSAO)
				textureMappingEffect->SetActiveTechniqueByName("Texture_AlphaClip");
			else
				textureMappingEffect->SetActiveTechniqueByName("Texture_AlphaClip_NoSSAOSample");
		}
	}

	//Set variables. 
	textureMappingEffect->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	textureMappingEffect->SetCBufferPerObject(world, worldInvTrans, worldViewProj, 
		texTrans, mat, worldView);
	textureMappingEffect->SetTextureMap(texture);
	textureMappingEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	textureMappingEffect->SetSSAOData(ssaoTex, SSAOTrans);
	textureMappingEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		textureMappingEffect->SetShadowMap(shadMap);
		textureMappingEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}
	//Bind buffers. 
	UINT stride = sizeof(TileForwardTextureMapFX::PosNormalTexVertex);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);

	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(textureMappingEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < textureMappingEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		textureMappingEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[7] = {0,0,0,0,0,0,0};
	context->PSSetShaderResources(0, 7, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardNormalMapFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, CXMMATRIX& texTrans, 
		Material& mat,
		ID3D11ShaderResourceView* texture,
		ID3D11ShaderResourceView* normalMap,
		unsigned drawCount,
		unsigned drawStart,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex, 
		bool shouldSampleSSAO)
{
	//Set technique
	if (isShadowPass)
		normalMappingEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			normalMappingEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else
		{
			if (shouldSampleSSAO)
				normalMappingEffect->SetActiveTechniqueByName("Tex_AlphaClip");
			else
				normalMappingEffect->SetActiveTechniqueByName("Tex_AlphaClip_NoSSAOSample");
		}
	}

	//Set variables. 
	normalMappingEffect->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	normalMappingEffect->SetCBufferPerObject(world, worldInvTrans, worldViewProj, 
		texTrans, mat, worldView);
	normalMappingEffect->SetShaderResources(texture, normalMap);
	normalMappingEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	normalMappingEffect->SetSSAOData(ssaoTex, SSAOTrans);
	normalMappingEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		normalMappingEffect->SetShadowMap(shadMap);
		normalMappingEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride = sizeof(TileForwardNormalMapFX::PosNormalTexTangentVertex);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(normalMappingEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < normalMappingEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		normalMappingEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[8] = {0,0,0,0,0,0,0,0};
	context->PSSetShaderResources(0, 8, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardDisplacementMapFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& viewProj, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, 
		CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture,
		ID3D11ShaderResourceView* dispMap,
		ID3D11ShaderResourceView* heightMap, //Optional.
		float heightScale, 
		float maxTessDist, float minTessDist, 
		float maxTessFact, float minTessFact,
		unsigned drawCount,
		unsigned drawStart,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, CXMMATRIX& view, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex, 
		bool shouldSampleSSAO)
{
	if (isShadowPass && heightMap)
		displacementMappingEffect->SetActiveTechniqueByName("ShadowMapRendering_SepHM");
	else if (isShadowPass)
		displacementMappingEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		//Set technique
		if (isZPrePass && heightMap)
			displacementMappingEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip_SepHM");
		else if (isZPrePass)
			displacementMappingEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else if (heightMap)
		{
			if (shouldSampleSSAO)
				displacementMappingEffect->SetActiveTechniqueByName("DisplacementMapping_AlphaClip_SepHM");
			else
				displacementMappingEffect->SetActiveTechniqueByName("DisplacementMapping_AlphaClip_SepHM_NoSSAOSample");
		}
		else
		{
			if (shouldSampleSSAO)
				displacementMappingEffect->SetActiveTechniqueByName("DisplacementMapping_AlphaClip");
			else
				displacementMappingEffect->SetActiveTechniqueByName("DisplacementMapping_AlphaClip_NoSSAOSample");
		}
	}
	//Set variables. 
	displacementMappingEffect->SetPerFrameCbuffer(eyePosition, dLights, dLightCount, 
		llib, llseb);
	displacementMappingEffect->SetPerObjectCbuffer(world, viewProj, worldInvTrans, worldViewProj, 
		texTrans, mat, worldView, view);
	displacementMappingEffect->SetShaderResources(dispMap, texture, heightMap);
	displacementMappingEffect->SetCbufferTessData(heightScale, maxTessDist, minTessDist, 
		maxTessFact, minTessFact);
	displacementMappingEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	displacementMappingEffect->SetSSAOData(ssaoTex, SSAOTrans);
	displacementMappingEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		displacementMappingEffect->SetShadowMap(shadMap);
		displacementMappingEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride = sizeof(TileForwardDisplacementMappingFX::PerVertexData);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(displacementMappingEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < displacementMappingEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		displacementMappingEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[8] = {0,0,0,0,0,0,0,0};
	ID3D11ShaderResourceView* srvNULLOne[1] = {0};
	context->PSSetShaderResources(0, 8, srvNULL);
	context->DSSetShaderResources(0, 1, srvNULLOne);

	//Reset DS and HS
	context->HSSetShader(0,0,0);
	context->DSSetShader(0,0,0);
}

void D3D11Renderer::RenderWithTileForwardSolidColourFX(ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, 
		Material& mat, 
		XMFLOAT3& modelColour, 
		unsigned drawCount, 
		unsigned drawStart, 
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex, 
		bool shouldSampleSSAO)
{
	//Set technique
	if (isShadowPass)
		tileForwardSolidColourEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			tileForwardSolidColourEffect->SetActiveTechniqueByName("ZPrePass");
		else
		{
			if (shouldSampleSSAO)
				tileForwardSolidColourEffect->SetActiveTechniqueByName("Colour");
			else
				tileForwardSolidColourEffect->SetActiveTechniqueByName("Colour_NoSSAOSample");
		}
	}
	//Set variables. 
	tileForwardSolidColourEffect->SetCBufferPerObject(world, worldInvTrans, 
		worldViewProj, mat, modelColour, worldView);
	tileForwardSolidColourEffect->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	tileForwardSolidColourEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	tileForwardSolidColourEffect->SetSSAOData(ssaoTex, SSAOTrans);
	tileForwardSolidColourEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		tileForwardSolidColourEffect->SetShadowMap(shadMap);
		tileForwardSolidColourEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride = sizeof(TileForwardSolidColourFX::PosNormalVertex);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(tileForwardSolidColourEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < tileForwardSolidColourEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		tileForwardSolidColourEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[6] = {0,0,0,0,0,0};
	context->PSSetShaderResources(0, 6, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardNormalMapInstFX(ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		ID3D11Buffer* instVertexBuffer,
		CXMMATRIX& viewProj, CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture,
		ID3D11ShaderResourceView* normalMap,
		unsigned drawCount,
		unsigned drawStart,
		unsigned instanceCount,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& view, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOToTexMatrix, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass)
		normalMappingInstEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			normalMappingInstEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else
			normalMappingInstEffect->SetActiveTechniqueByName("Tex_AlphaClip");
	}

	//Set variables. 
	normalMappingInstEffect->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	normalMappingInstEffect->SetCBufferPerDrawCall(viewProj, texTrans, mat, view);
	normalMappingInstEffect->SetShaderResources(texture, normalMap);
	normalMappingInstEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	normalMappingInstEffect->SetSSAOData(ssaoTex, SSAOToTexMatrix);
	normalMappingInstEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		normalMappingInstEffect->SetShadowMap(shadMap);
		normalMappingInstEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers - Note: we have two. [0] == Per vertex data [1] == Per instance data 
	UINT stride[] =
	{
		sizeof(TileForwardNormalMapInstFX::PerVertexData),
		sizeof(TileForwardNormalMapInstFX::PerInstancedData)
	};
	UINT offset[] = {0,0};
	ID3D11Buffer* vbInput[] = {vb, instVertexBuffer};

	//Bind two vertex buffers. 
	context->IASetVertexBuffers(0, 2, &vbInput[0], &stride[0], &offset[0]);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(normalMappingInstEffect->ReturnInputLayout());

	//Draw - use isntanced calls. 
	for (unsigned i = 0; i < normalMappingInstEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		normalMappingInstEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexedInstanced(drawCount, instanceCount, drawStart, 0, 0);
		else
			context->DrawInstanced(drawCount, instanceCount, drawStart, 0);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[8] = {0,0,0,0,0,0,0,0};
	context->PSSetShaderResources(0, 8, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardTextureMapInstFX(ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		ID3D11Buffer* instVertexBuffer,
		CXMMATRIX& viewProj, CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture,
		unsigned drawCount,
		unsigned drawStart,
		unsigned instanceCount,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& view, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOToTexMatrix, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass)
		textureMappingInstEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			textureMappingInstEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else
			textureMappingInstEffect->SetActiveTechniqueByName("Texture_AlphaClip");
	}

	//Set variables. 
	textureMappingInstEffect->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	textureMappingInstEffect->SetCBufferPerObject(viewProj,	texTrans, mat, view);
	textureMappingInstEffect->SetTextureMap(texture);
	textureMappingInstEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	textureMappingInstEffect->SetSSAOData(ssaoTex, SSAOToTexMatrix);
	textureMappingInstEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		textureMappingInstEffect->SetShadowMap(shadMap);
		textureMappingInstEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers - Note, 2 VB are bound.  
	UINT stride[] = 
	{
		sizeof(TileForwardTextureMapInstFX::PerVertex),
		sizeof(TileForwardTextureMapInstFX::PerInstance)
	};
	UINT offset[] = {0, 0};
	ID3D11Buffer* vbs[] = {vb, instVertexBuffer};

	//VBs
	context->IASetVertexBuffers(0, 2, &vbs[0], &stride[0], &offset[0]);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);

	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(textureMappingInstEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < textureMappingInstEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		textureMappingInstEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexedInstanced(drawCount, instanceCount, drawStart, 0, 0);
		else
			context->DrawInstanced(drawCount, instanceCount, drawStart, 0);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[7] = {0,0,0,0,0,0,0};
	context->PSSetShaderResources(0, 7, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardSolidColourInstFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		ID3D11Buffer* instancedBuffer,
		CXMMATRIX& viewProj,
		Material& mat, 
		XMFLOAT3& modelColour, 
		unsigned drawCount, 
		unsigned drawStart, 
		unsigned instanceCount,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& view, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOToTexMatrix, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass)
		solidColourInstEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			solidColourInstEffect->SetActiveTechniqueByName("ZPrePass");
		else
			solidColourInstEffect->SetActiveTechniqueByName("Colour");
	}

	//Set variables. 
	solidColourInstEffect->SetCBufferPerObject(viewProj, mat, modelColour, view);
	solidColourInstEffect->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	solidColourInstEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	solidColourInstEffect->SetSSAOData(ssaoTex, SSAOToTexMatrix);
	solidColourInstEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		solidColourInstEffect->SetShadowMap(shadMap);
		solidColourInstEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers - 2 vbs
	UINT stride[] = 
	{
		sizeof(TileForwardSolidColourInstFX::PerVertex),
		sizeof(TileForwardSolidColourInstFX::PerInstance)
	};
	UINT offset[] = {0, 0};
	ID3D11Buffer* vbs[] = {vb, instancedBuffer};

	//VB
	context->IASetVertexBuffers(0, 2, &vbs[0], &stride[0], &offset[0]);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(solidColourInstEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < solidColourInstEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		solidColourInstEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexedInstanced(drawCount, instanceCount, drawStart, 0, 0);
		else
			context->DrawInstanced(drawCount, instanceCount, drawStart, 0);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[6] = {0,0,0,0,0,0};
	context->PSSetShaderResources(0, 6, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardDisplacementMapInstFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		ID3D11Buffer* instancedBuffer,
		CXMMATRIX& viewProj, CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture,
		ID3D11ShaderResourceView* dispMap,
		ID3D11ShaderResourceView* heightMap, //Optional (Seperate height map)
		float heightScale, 
		float maxTessDist, float minTessDist, 
		float maxTessFact, float minTessFact,
		unsigned drawCount,
		unsigned drawStart,
		unsigned instanceCount,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& view, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOToTexMatrix, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass && heightMap)
		dispMappingInstEffect->SetActiveTechniqueByName("ShadowMapRendering_SepHM");
	else if (isShadowPass)
		dispMappingInstEffect->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass && heightMap)
			dispMappingInstEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip_SepHM");
		else if (isZPrePass)
			dispMappingInstEffect->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else if (heightMap)
			dispMappingInstEffect->SetActiveTechniqueByName("DisplacementMapping_AlphaClip_SepHM");
		else
			dispMappingInstEffect->SetActiveTechniqueByName("DisplacementMapping_AlphaClip");
	}

	//Set variables. 
	dispMappingInstEffect->SetPerFrameCbuffer(eyePosition, dLights, dLightCount, 
		llib, llseb);
	dispMappingInstEffect->SetPerObjectCbuffer(viewProj, texTrans, mat, view);
	dispMappingInstEffect->SetShaderResources(dispMap, texture, heightMap);
	dispMappingInstEffect->SetCbufferTessData(heightScale, maxTessDist, minTessDist, 
		maxTessFact, minTessFact);
	dispMappingInstEffect->SetHemisphericalData(hemiColDown, hemiColRange);
	dispMappingInstEffect->SetSSAOData(ssaoTex, SSAOToTexMatrix);
	dispMappingInstEffect->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		dispMappingInstEffect->SetShadowMap(shadMap);
		dispMappingInstEffect->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride[] = 
	{
		sizeof(TileForwardDisplacementMapInstFX::PerVertexData),
		sizeof(TileForwardDisplacementMapInstFX::PerInstanceData)
	};
	UINT offset[] = {0, 0};
	ID3D11Buffer* vbs[] = {vb, instancedBuffer};

	//VB
	context->IASetVertexBuffers(0, 2, &vbs[0], &stride[0], &offset[0]);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(dispMappingInstEffect->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < dispMappingInstEffect->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		dispMappingInstEffect->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexedInstanced(drawCount, instanceCount, drawStart, 0, 0);
		else
			context->DrawInstanced(drawCount, instanceCount, drawStart, 0);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[8] = {0,0,0,0,0,0,0,0};
	ID3D11ShaderResourceView* srvNULLOne[1] = {0};
	context->PSSetShaderResources(0, 8, srvNULL);
	context->DSSetShaderResources(0, 1, srvNULLOne);

	//Reset DS and HS
	context->HSSetShader(0,0,0);
	context->DSSetShader(0,0,0);
}

void D3D11Renderer::RenderWithTileForwardAnimNormalMapFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture,
		ID3D11ShaderResourceView* normalMap,
		unsigned drawCount,
		unsigned drawStart,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology,
		XMFLOAT4X4* finalTransforms, unsigned boneCount, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass)
		animNormalMapFX->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			animNormalMapFX->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else
			animNormalMapFX->SetActiveTechniqueByName("Tex_AlphaClip");
	}
	//Set variables. 
	animNormalMapFX->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	animNormalMapFX->SetPerObjectCbuffer(world, worldInvTrans, worldViewProj, 
		texTrans, mat, worldView);
	animNormalMapFX->SetShaderResources(texture, normalMap);
	animNormalMapFX->SetAnimationBoneTransformArray(finalTransforms, boneCount);
	animNormalMapFX->SetHemisphericalData(hemiColDown, hemiColRange);
	animNormalMapFX->SetSSAOData(ssaoTex, SSAOTrans);
	animNormalMapFX->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		animNormalMapFX->SetShadowMap(shadMap);
		animNormalMapFX->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride = sizeof(TileForwardAnimNormalMapFX::PerVertex);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(animNormalMapFX->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < animNormalMapFX->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		animNormalMapFX->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[8] = {0,0,0,0,0,0,0,0};
	context->PSSetShaderResources(0, 8, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardAnimTextureMapFX(ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, CXMMATRIX& texTrans, 
		Material& mat, 
		ID3D11ShaderResourceView* texture,
		unsigned drawCount,
		unsigned drawStart,
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT4X4* finalTransforms, unsigned boneCount, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass)
		animTexMapFX->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			animTexMapFX->SetActiveTechniqueByName("ZPrePass_AlphaClip");
		else
			animTexMapFX->SetActiveTechniqueByName("Tex_AlphaClip");
	}

	//Set variables. 
	animTexMapFX->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	animTexMapFX->SetPerObjectCbuffer(world, worldInvTrans, worldViewProj, 
		texTrans, mat, worldView);
	animTexMapFX->SetShaderResources(texture);
	animTexMapFX->SetAnimationBoneTransformArray(finalTransforms, boneCount);
	animTexMapFX->SetHemisphericalData(hemiColDown, hemiColRange);
	animTexMapFX->SetSSAOData(ssaoTex, SSAOTrans);
	animTexMapFX->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		animTexMapFX->SetShadowMap(shadMap);
		animTexMapFX->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride = sizeof(TileForwardAnimTextureMapFX::PerVertex);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(animTexMapFX->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < animTexMapFX->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		animTexMapFX->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[7] = {0,0,0,0,0,0,0};
	context->PSSetShaderResources(0, 7, srvNULL);
}

void D3D11Renderer::RenderWithTileForwardAnimSolidColourFX(
		ID3D11DeviceContext* context,
		XMFLOAT3& eyePosition, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* llib, ID3D11ShaderResourceView* llseb,
		ID3D11Buffer* vb, ID3D11Buffer* ib, 
		CXMMATRIX& world, CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, 
		Material& mat, 
		XMFLOAT3& modelColour, 
		unsigned drawCount, 
		unsigned drawStart, 
		bool isZPrePass, 
		D3D11_PRIMITIVE_TOPOLOGY topology, 
		XMFLOAT4X4* finalTransforms, unsigned boneCount, 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange, 
		CXMMATRIX& worldView, 
		ID3D11ShaderResourceView* ssaoTex,
		CXMMATRIX& SSAOTrans, 
		ID3D11ShaderResourceView* envMap, 
		bool isShadowPass, 
		ID3D11ShaderResourceView* shadMap,
		CXMMATRIX &shadowMapView, 
		CXMMATRIX &shadowMapProj, 
		CXMMATRIX &shadowMapToTex)
{
	//Set technique
	if (isShadowPass)
		animSolidColourFX->SetActiveTechniqueByName("ShadowMapRendering");
	else
	{
		if (isZPrePass)
			animSolidColourFX->SetActiveTechniqueByName("ZPrePass");
		else
			animSolidColourFX->SetActiveTechniqueByName("Colour");
	}

	//Set variables. 
	animSolidColourFX->SetPerObjectCbuffer(world, worldInvTrans, 
		worldViewProj, mat, modelColour, worldView);
	animSolidColourFX->SetLightingData(eyePosition, dLights, dLightCount, 
		llib, llseb);
	animSolidColourFX->SetAnimationBoneTransformArray(finalTransforms, boneCount);
	animSolidColourFX->SetHemisphericalData(hemiColDown, hemiColRange);
	animSolidColourFX->SetSSAOData(ssaoTex, SSAOTrans);
	animSolidColourFX->SetEnvironmentMap(envMap);
	if (!isShadowPass)
	{
		animSolidColourFX->SetShadowMap(shadMap);
		animSolidColourFX->SetShadowMapMatricies(shadowMapView, shadowMapProj, shadowMapToTex);
	}

	//Bind buffers. 
	UINT stride = sizeof(TileForwardAnimSolidColourFX::PerVertex);
	UINT offset = 0;

	//VB
	context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
	//Optional IB
	if (ib)
		context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);


	//Set Primitive topology.
	context->IASetPrimitiveTopology(topology);
	context->IASetInputLayout(animSolidColourFX->ReturnInputLayout());

	//Draw
	for (unsigned i = 0; i < animSolidColourFX->ReturnActiveTechniqueNumberOfPasses(); i++)
	{
		animSolidColourFX->ApplyActiveTechniqueForPass(i, context);
		if (ib)
			context->DrawIndexed(drawCount, drawStart, 0);
		else
			context->Draw(drawCount, drawStart);
	}

	//Unbind SRVs.
	ID3D11ShaderResourceView* srvNULL[6] = {0,0,0,0,0,0};
	context->PSSetShaderResources(0, 6, srvNULL);
}